package com.sharp.authorization.service.area.impl;

import com.sharp.authorization.dao.common.entity.SaArea;
import com.sharp.authorization.dao.common.repository.SaAreaService;
import com.sharp.authorization.service.area.AreaService;
import com.sharp.authorization.vo.area.AreaInfoRes;
import com.sharp.kernel.utils.JsonUtil;
import com.sharp.kernel.utils.ReflectionUtil;
import com.sharp.framework.utils.XMLUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Title: AreaServiceImpl
 * Description: Copyright: Copyright (c) 2019 Company: BHFAE
 *
 * @author Sharp
 * @date 2020/5/1 15:06
 * @description Project Name: Seed
 * @Package: com.srct.service.account.service.area.impl
 */
@Service
public class AreaServiceImpl implements AreaService {

    private static final String VERSION = "international_eub_us_1.1";
    private static final String AUTHENTICATE = "pdfTest_dhfjh98983948jdf78475fj65375fjdhfj";
    private static final String API_TYPE_PROVINCE = "getProvinceList";
    private static final String API_TYPE_CITY = "getCityList";
    private static final String API_TYPE_COUNTY = "getCountyList";
    private static final String EMS_SYNC_URL = "http://shipping.ems.com.cn/apiService/xmlResultForApi";
    private static Map<Integer, Map<String, String>> dataMap;
    private static Map<Integer, String> parentNameMap;

    @Resource
    private SaAreaService saAreaService;

    @Override
    public List<AreaInfoRes> getAreaInfo(String parentCode) {
        List<SaArea> areaList = saAreaService.getAreaInfoByParentCode(parentCode);
        return ReflectionUtil.copyList(areaList, AreaInfoRes.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncAreaInfo() {
        saAreaService.truncate();
        try {
            sync(1, null);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @PostConstruct
    public void initMap() {
        dataMap = new HashMap<>(3);
        parentNameMap = new HashMap<>(2);
        Map<String, String> provinceMap = buildMap(API_TYPE_PROVINCE);
        dataMap.put(1, provinceMap);
        Map<String, String> cityMap = buildMap(API_TYPE_CITY);
        dataMap.put(2, cityMap);
        parentNameMap.put(2, "province");
        Map<String, String> countyMap = buildMap(API_TYPE_COUNTY);
        dataMap.put(3, countyMap);
        parentNameMap.put(3, "city");
    }

    private Map<String, String> buildMap(String apiType) {
        Map<String, String> data = new HashMap<>(4);
        data.put("version", VERSION);
        data.put("authenticate", AUTHENTICATE);
        data.put("apiType", apiType);
        return data;
    }

    private void sync(Integer level, String parentCode) throws IOException {
        Map<String, String> data = dataMap.get(level);
        if (data == null) {
            return;
        }
        if (parentNameMap.get(level) != null) {
            data.put(parentNameMap.get(level), parentCode);
        }
        Document doc = Jsoup.connect(EMS_SYNC_URL).data(data).post();
        Elements element = doc.getElementsByTag("textarea");
        List<TextNode> textNodeList = element.textNodes();
        String xml = textNodeList.get(0).text();
        List nodeList = XMLUtil.toNormalObject(xml, List.class);
        if (CollectionUtils.isEmpty(nodeList)) {
            return;
        }
        for (Object o : nodeList) {
            LinkedHashMap<String, String> res = JsonUtil.readJson(o, LinkedHashMap.class, String.class, String.class);
            if (StringUtils.isNotBlank(res.get("id"))) {
                SaArea area = new SaArea();
                area.setCode(res.get("id"));
                area.setLevel(level);
                area.setParentCode(parentCode);
                area.setName(res.get(""));
                saAreaService.insertSelective(area);
                sync(level + 1, area.getCode());
            }
        }

    }

}
